#include "BlockQuad.h"
using namespace std;
/*!
\brief Create a quadrangular block.
\param a,b,c,d End vertices of the parcel.
*/
BlockQuad::BlockQuad(const Vector& a,const Vector& b,const Vector& c,const Vector& d):Quadrangle(a,b,c,d){
	int tailleCour = 0;
}
void BlockQuad::Subdivide(){
	BlockQuad bq = clone2(0.35);
	BlockQuad * extrem[4];

	bool b= true;
	if(bq.Area()>tailleMinimumCour){
		if(true){//mettre un random pour la division differentes des blocs de coins
			for(int t = 0 ; t<4;t++){
				int precedent = (t+3)%4;
				int suivant = (t+1) %4;
				Vector x = Intersection2(p[t], p[suivant], bq[t], bq[precedent]);
				Vector y = Intersection2(p[t], p[precedent], bq[t], bq[suivant]);
				extrem[t] = new BlockQuad( bq[t],y,p[t],x);
				if(extrem[t]->Area()<.1){
					b = false;
				}
			}
			if(b){

				for(int t = 0 ; t<4;t++){
					EtagesQuad(extrem[t]->clone2(0.97), 1).CreerEtage();
				}
				for(int t = 0 ; t<4;t++){
					int precedent = (t+3)%4;
					int suivant = (t+1) %4;
					BlockQuad bd1 = *extrem[t];
					BlockQuad bd2 = *extrem[suivant];
					BlockQuad cv = BlockQuad(bq[t],bd1[3],bd2[1], bq[suivant]);
					cv.divise();
				}
			}else{
				int pos[2];
				getPointProches(pos);
				pos[0] = (pos[0]+2) %4;
				pos[1] = (pos[1]+2) %4;
				BlockQuad cv = BlockQuad(bq[pos[0]],bq[pos[1]],p[pos[1]],p[pos[0]]);
				cv.divise();
			}
			
		}else{
			int j;
		}
	}else{
		this->divise();
	}
}

void BlockQuad::getPointProches(int pos[2] ){
	 pos[0] = 0;
	 pos[1] = 1;
		if(Norm(p[1]-p[2])<Norm(p[pos[0]]-p[pos[1]])){
			pos[0] = 1;
			pos[1] = 2;
		}

		if(Norm(p[3]-p[2])<Norm(p[pos[0]]-p[pos[1]])){
			pos[1] = 3;
			pos[0] = 2;
		}
		if(Norm(p[3]-p[0])<Norm(p[pos[0]]-p[pos[1]])){
			pos[1] = 3;
			pos[0] = 0;
		}
}
void BlockQuad::divise(){
	double longeurTotale = Norm(p[2]-p[1]);
	if(longeurTotale>2.0*Util::longeurBatimentMinimale){
		Vector x = (p[2]+p[1])/2;
		Vector y = (p[3]+p[0])/2;
		BlockQuad(p[0], p[1], x,y).divise();
		BlockQuad( y, x,p[2],p[3]).divise();
	}else{
		EtagesQuad(this->clone2(0.95), 1).CreerEtage();
	}
} 
BlockQuad BlockQuad::clone2(double scalaire){
	Vector intersect = Intersection2(p[0], p[2],p[1], p[3]);
	Vector p2[4];
	p2[2]= Util::getPartie(intersect, p[2], scalaire);
	p2[3]= Util::getPartie(intersect, p[3], scalaire);
	p2[0]=Util::getPartie(intersect, p[0], scalaire);
	p2[1]=Util::getPartie(intersect, p[1], scalaire);

	return BlockQuad(p2[0], p2[1], p2[2],p2[3]);
}
BlockQuad BlockQuad::clone3(double scalaire){
	Vector intersect = Intersection2((p[0]+p[1])/2.0,(p[2]+p[3])/2.0,(p[1]+p[2])/2.0,(p[3]+p[0])/2.0);
	Vector p2[4];
	p2[2]= Util::getPartie(intersect, p[2], scalaire);
	p2[3]= Util::getPartie(intersect, p[3], scalaire);
	p2[0]=Util::getPartie(intersect, p[0], scalaire);
	p2[1]=Util::getPartie(intersect, p[1], scalaire);

	return BlockQuad(p2[0], p2[1], p2[2],p2[3]);
}

BlockQuad BlockQuad::clone(double scalaire){
	Vector p2[4];
	
	p2[0]= Util::getPartie(p[0], p[2], scalaire);
	p2[1]= Util::getPartie(p[1], p[3], scalaire);
	p2[2]=Util::getPartie(p[2], p[0], scalaire);
	p2[3]=Util::getPartie(p[3], p[1], scalaire);
	return BlockQuad(p2[0], p2[1], p2[2],p2[3]);
}
BlockQuad BlockQuad::Shrink(const double& ab,const double& bc, const double& cd, const double& da)
{
  Vector sa = p[0]-Normalized((p[1]-p[0])/Vector(0,0,1))*ab;
  Vector sb = p[1]-Normalized((p[2]-p[1])/Vector(0,0,1))*bc;
  Vector sc = p[2]-Normalized((p[3]-p[2])/Vector(0,0,1))*cd;
  Vector sd = p[3]-Normalized((p[0]-p[3])/Vector(0,0,1))*da;
  return BlockQuad(
    Intersection2(sa,sa+(p[1]-p[0]),sb,sb+(p[2]-p[1])),
    Intersection2(sb,sb+(p[2]-p[1]),sc,sc+(p[3]-p[2])),
    Intersection2(sc,sc+(p[3]-p[2]),sd,sd+(p[0]-p[3])),
    Intersection2(sd,sd+(p[0]-p[3]),sa,sa+(p[1]-p[0])));
}

void BlockQuad::separation(){
	barriere();
}

void BlockQuad::barriere(){
	double tailleRamp = (double)Util::randomBorne(80, 120) * Util::tailleRampe/ 100.0;
	BlockQuad bas = BlockQuad(p[0],p[1],p[2],p[3]);
	Vector hauteurRampe = Vector(0,0,tailleRamp);
	Vector hauteurBarriere = Vector(0,0,Util::tailleBarriere);
	PrismQuad(bas,tailleRamp).Render();
	 
	double tailleBarr = (double)Util::randomBorne(80, 120) * Util::tailleBarriere/ 100.0;
	double taillePan = (double)Util::randomBorne(80, 120) * Util::taillePanneau/ 100.0;
	double tailleA = Norm(p[0]-p[1]);
	double tailleB = Norm(p[3]-p[2]);
	int nbPaneau = tailleA/(taillePan);
	for(int i= 0; i<nbPaneau -10; i= i +3){
		Vector x1 =Util::getPartie(p[0],p[1], i * taillePan/tailleA);
		Vector x2 =Util::getPartie(p[0],p[1], (i +1) * taillePan/tailleA);

		Vector y1 =Util::getPartie(p[3],p[2], i * taillePan/tailleB);
		Vector y2 =Util::getPartie(p[3],p[2], (i +1) * taillePan/tailleB);

		PrismQuad(x1+ hauteurRampe, x2+ hauteurRampe, y2+ hauteurRampe, y1+ hauteurRampe, tailleBarr).Render();
	}
	
	BlockQuad haut = BlockQuad (bas[0]+hauteurBarriere+hauteurRampe,bas[1]+hauteurBarriere+hauteurRampe,bas[2]+hauteurBarriere+hauteurRampe,bas[3]+hauteurBarriere+hauteurRampe);
	PrismQuad(haut,tailleRamp).Render();
}